package com.platform.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.platform.dao.UserDao;
import com.platform.dao.UserReferrerPeriodDao;
import com.platform.entity.*;
import com.platform.service.*;
import com.platform.utils.DateUtils;
import com.platform.utils.R;
import com.platform.utils.RRException;
import com.platform.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Service实现类
 *
 * @author lipengjun
 * @email 939961241@qq.com
 * @date 2017-08-16 15:02:28
 */
@Service("userService")
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Autowired
    private UserLevelService userLevelService;

    @Autowired
    private UserLevelPeriodService userLevelPeriodService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private UserReferrerPeriodDao userReferrerPeriodDao;

    @Autowired
    private UserFreezeAccountService userFreezeAccountService;

    @Autowired
    private UserTransactionRecordService userTransactionRecordService;


    @Override
    public UserEntity queryObject(Integer id) {
        return userDao.queryObject(id);
    }

    @Override
    public List<UserEntity> queryList(Map<String, Object> map) {
        return userDao.queryList(map);
    }

    @Override
    public int queryTotal(Map<String, Object> map) {
        return userDao.queryTotal(map);
    }

    @Override
    @Transactional
    public int save(UserEntity user) {
        user.setRegisterTime(new Date());
        UserReferrerPeriodEntity userReferrerPeriodEntity = new UserReferrerPeriodEntity();
        userReferrerPeriodEntity.setReferrerId(user.getReferrerId());
        userReferrerPeriodEntity.setUserId(user.getId());
        userReferrerPeriodEntity.setReferrerStart(new Date());
        userReferrerPeriodEntity.setReferrerEnd(DateUtils.strToDate("20990101000000000"));
        userReferrerPeriodDao.save(userReferrerPeriodEntity);
        return userDao.save(user);
    }

    @Override
    public int update(UserEntity user) {
        if (user.getReferrerId() != null){
            UserEntity dbValue = queryObject(user.getId());
            if (!dbValue.getReferrerId().equals(user.getReferrerId())){
                //上级更改，记录时间
                UserReferrerPeriodEntity userReferrerPeriodEntity = userReferrerPeriodDao.queryLast(user.getId());
                if (userReferrerPeriodEntity != null){
                    userReferrerPeriodEntity.setReferrerEnd(new Date());
                    userReferrerPeriodDao.update(userReferrerPeriodEntity);
                }
                userReferrerPeriodEntity = new UserReferrerPeriodEntity();
                userReferrerPeriodEntity.setUserId(user.getId());
                userReferrerPeriodEntity.setReferrerId(user.getReferrerId());
                userReferrerPeriodEntity.setReferrerStart(new Date());
                userReferrerPeriodEntity.setReferrerEnd(DateUtils.strToDate("20990101000000000"));
                userReferrerPeriodDao.save(userReferrerPeriodEntity);
            }
        }
        return userDao.update(user);
    }

    @Override
    public int delete(Integer id) {
        return userDao.delete(id);
    }

    @Override
    public int deleteBatch(Integer[] ids) {
        return userDao.deleteBatch(ids);
    }


    @Override
    public String getUserList(Integer rootId) {
        return userDao.getUserList(rootId);
    }

    @Override
    public long countUserChildListByLevel(Integer rootId, Integer levelId) {
        return Arrays.stream(userDao.getUserChildListByLevel(rootId, levelId).split(",")).filter(t->!t.equals("-1") && !t.equals(rootId + "")).count();
    }

    @Override
    public int unFreezeAccount(Long userId, BigDecimal freezeAccount) {
        return userDao.unFreezeAccount(userId, freezeAccount);
    }



    @Transactional
    @Override
    public R batchAddCommissions(List<String[]> list) {
        for (int i = 1; i < list.size(); i++){
            if (StringUtils.isNullOrEmpty(list.get(i))) continue;

            Long userId = Long.valueOf(list.get(i)[0]);
            // 1 佣金    2 退款
            String typeDesc = list.get(i)[1];
            String type;
            if (typeDesc.equals("佣金")){
                type = "1";
            } else if (typeDesc.equals("退款")){
                type = "2";
            } else {
                throw new RRException("用户ID为" + userId + "的用户，增加" + typeDesc +"不合法，当前批量增加全部回滚！");
            }
            BigDecimal commission = new BigDecimal(list.get(i)[2]);
            int result = addCommission(userId, type, typeDesc, commission);
            if (result != 1){
                throw new RRException("用户ID为" + userId + "的用户，增加失败" + typeDesc + "，当前批量增加全部回滚！");
            }
        }
        return R.ok();
    }

    @Override
    public int addCommission(Long userId, String type, String typeDesc, BigDecimal commission) {
        int r =  userDao.addCommission(userId, commission);
        if (r == 0){
            return r;
        }

        //保存折扣交易记录
        UserTransactionRecordEntity userTransactionRecordEntity = new UserTransactionRecordEntity();
        userTransactionRecordEntity.setMoney(commission);
        userTransactionRecordEntity.setUserId(userId);
        userTransactionRecordEntity.setTransactionUserId(userId);
        userTransactionRecordEntity.setType(type.equals("1") ? UserTransactionRecordEntity.TRANSACTION_TYPE_ADD_COMMISSION : UserTransactionRecordEntity.TRANSACTION_TYPE_REFUND);
        userTransactionRecordEntity.setRemark(typeDesc + commission.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "元");
        userTransactionRecordEntity.setOrderGoodsId(-1l);
        userTransactionRecordEntity.setOrderId(-1l);
        return userTransactionRecordService.save(userTransactionRecordEntity);
    }

    @Override
    public int decreaseAccount(Long userId, BigDecimal account) {
        return userDao.decreaseAccount(userId, account);
    }


    @Override
    @Transactional
    public R batchUpdateUserLevel(Map param) {
        List<String> ids = (List<String>)param.get("ids");
        Integer userLevelId = (Integer)param.get("userLevelId");
        for (String id : ids){
            UserEntity userEntity = queryObject(Integer.valueOf(id));
            if (userEntity.getIsSystemCalc().equals(1)){
                throw new RRException("用户ID为" + id + "的用户" + userEntity.getNickname() +"级别由系统自动计算，无法手动更新");
            }

            userEntity.setUserLevelId(userLevelId);
            update(userEntity);
        }
        return R.ok();
    }

    @Transactional
    @Override
    public void refreshUserLevel() {
        //获取规则
        UserLevelEntity rule = userLevelService.queryRule();
        if (rule != null && StringUtils.isNotEmpty(rule.getName())){
            JSONObject ruleObj = JSONObject.parseObject(rule.getName());
            //普通->高级会员
            Integer param1 = ruleObj.getInteger("param1");

            //高级会员->掌柜
            Integer param2 = ruleObj.getInteger("param2");
            BigDecimal param3 = ruleObj.getBigDecimal("param3");

            //掌柜->运营商
            Integer param4 = ruleObj.getInteger("param4");
            BigDecimal param5 = ruleObj.getBigDecimal("param5");

            //运营商->合伙人
            Integer param6 = ruleObj.getInteger("param6");
            BigDecimal param7 = ruleObj.getBigDecimal("param7");


            //查询所有的客户
            List<UserEntity> users = userDao.queryList(null);
            for (UserEntity user : users){
                if (user.getIsSystemCalc().equals(0)){
                    continue;
                }
                String subUsers = getUserList(user.getId());
                List<Integer> hits = Lists.newArrayList();
                //普通->高级会员
                //查询推荐普通会员个数
                Map param = Maps.newHashMap();
                param.put("referrerId", user.getId());
                int count = userDao.queryTotal(param);
                if (count < param1.intValue()){
                    hits.add(UserLevelEntity.USER_LEVEL_1);
                } else {
                    hits.add(UserLevelEntity.USER_LEVEL_2);
                }

                BigDecimal totalPrice = orderService.getSubUsersOrderPrice(subUsers);

                //高级会员->掌柜
                if (count >= param2.intValue() && totalPrice.compareTo(param3) >= 0){
                    hits.add(UserLevelEntity.USER_LEVEL_3);
                }

                //掌柜->运营商
                count = Long.valueOf(countUserChildListByLevel(user.getId(), UserLevelEntity.USER_LEVEL_3)).intValue();
                if (count >= param4.intValue() && totalPrice.compareTo(param5) >= 0){
                    hits.add(UserLevelEntity.USER_LEVEL_4);
                }

                //运营商->合伙人
                count = Long.valueOf(countUserChildListByLevel(user.getId(), UserLevelEntity.USER_LEVEL_4)).intValue();
                if (count >= param6.intValue() && totalPrice.compareTo(param7) >= 0){
                    hits.add(UserLevelEntity.USER_LEVEL_5);
                }

                insertUserLevelDate(user.getId(), user.getUserLevelId(), hits);

            }

        }
    }



    private static List<Integer> levelSort = Lists.newArrayList();

    static {
        levelSort.add(UserLevelEntity.USER_LEVEL_1);
        levelSort.add(UserLevelEntity.USER_LEVEL_2);
        levelSort.add(UserLevelEntity.USER_LEVEL_3);
        levelSort.add(UserLevelEntity.USER_LEVEL_4);
        levelSort.add(UserLevelEntity.USER_LEVEL_5);
    }

    @Transactional
    public void insertUserLevelDate(Integer userId, Integer oldLevelId, List<Integer> hits){
        //更新最后一条记录
        UserLevelPeriodEntity userLevelPeriodEntity = userLevelPeriodService.queryLast(userId);
        if (userLevelPeriodEntity == null){
            userLevelPeriodEntity = new UserLevelPeriodEntity();
            userLevelPeriodEntity.setUserId(userId);
            userLevelPeriodEntity.setLevelId(hits.get(hits.size() - 1));
            userLevelPeriodEntity.setLevelStart(new Date());
            userLevelPeriodEntity.setLevelEnd(DateUtils.strToDate("20990101000000000"));
            userLevelPeriodService.save(userLevelPeriodEntity);
        } else {
            List<Integer> needSaves = Lists.newArrayList();
            Integer maxHitLevel = hits.get(hits.size() - 1);

            int index = levelSort.indexOf(maxHitLevel);

            int curIndex = 0;
            for (int i = 0 ; i < levelSort.size(); i++){
                if (levelSort.get(i).equals(oldLevelId)){
                    curIndex = i;
                    break;
                }
            }

            if (curIndex < index){
                for (int i = curIndex + 1; i <= index; i++){
                    needSaves.add(levelSort.get(i));
                }
            } else if (curIndex > index){
                for (int i = curIndex - 1; i >= index; i--){
                    needSaves.add(levelSort.get(i));
                }
            }



            if (needSaves.size() > 0){
                userLevelPeriodEntity.setLevelId(oldLevelId);
                userLevelPeriodEntity.setLevelEnd(new Date());
                userLevelPeriodService.update(userLevelPeriodEntity);

                for (int i = 0; i < needSaves.size(); i++){
                    Integer level = needSaves.get(i);
                    //查询新记录
                    UserLevelPeriodEntity temp = new UserLevelPeriodEntity();
                    temp.setUserId(userId);
                    temp.setLevelId(level);
                    temp.setLevelStart(new Date());
                    if (i == needSaves.size() - 1){
                        temp.setLevelEnd(DateUtils.strToDate("20990101000000000"));
                    } else {
                        temp.setLevelEnd(temp.getLevelStart());
                    }
                    userLevelPeriodService.save(temp);
                }

                UserEntity userEntity = new UserEntity();
                userEntity.setId(userId);
                userEntity.setUserLevelId(needSaves.get(needSaves.size() - 1));
                update(userEntity);
            }
        }



    }


    @Override
    @Transactional
    public void refreshUserFreezeAccount() {
        List<UserFreezeAccountEntity> list = userFreezeAccountService.queryFreezeEnd();
        if (list != null && list.size() > 0){
            for (UserFreezeAccountEntity item : list){
                unFreezeAccount(item.getUserId(), item.getAccount());
            }

            userFreezeAccountService.updateDeal(list.stream().map(t->t.getId()).collect(Collectors.toList()));
        }
    }



}
